﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using Chess.Models;
using System.Net;
using Newtonsoft.Json.Linq;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
using System.Security.Cryptography;
using System.Text;

namespace Chess.Controllers
{
    public class AccountController : Controller
    {
        private static OpenIdRelyingParty openid = new OpenIdRelyingParty();
        public IFormsAuthenticationService FormsService { get; set; }
        public IMembershipService MembershipService { get; set; }
        protected override void Initialize(RequestContext requestContext)
        {
            if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
            if (MembershipService == null) { MembershipService = new AccountMembershipService(); }

            base.Initialize(requestContext);
        }

        public ActionResult DangKyTaiKhoan(HomeModel model)
        {
            bool thongTinHopLe = true;
            Session["MessageType"] = "KetQuaDangKy";
            if (string.IsNullOrEmpty(model.DKUserName) || string.IsNullOrEmpty(model.DKPassword) || string.IsNullOrEmpty(model.DKNhapLaiMatKhau) || string.IsNullOrEmpty(model.DKHoTen))
            {
                thongTinHopLe = false;
                Session["KetQuaDangKy"] = "Đăng ký thất bại! Thông tin đăng ký không hợp lệ !";    
            }

            if (model.DKNhapLaiMatKhau.CompareTo(model.DKPassword)!=0)
            {
                thongTinHopLe = false;
                Session["KetQuaDangKy"] = "Đăng ký thất bại! Mật khẩu không chính xác !";  
            }

            HttpClient client;
            client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:3333/");
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            HttpResponseMessage response = client.GetAsync("api/TaiKhoan/" + model.DKUserName).Result;            
            if (response.IsSuccessStatusCode)
            {
                TaiKhoan taiKhoan = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
                if (taiKhoan != null)
                {
                    thongTinHopLe = false;
                    Session["KetQuaDangKy"] = "Đăng ký thất bại! Username đã tồn tại !";  
                }
            }


            if (thongTinHopLe)
            {
                TaiKhoan taiKhoan = new TaiKhoan();
                taiKhoan.UserName = model.DKUserName;
                taiKhoan.Password = model.DKPassword;
                taiKhoan.HoTen = model.DKHoTen;
                taiKhoan.NgaySinh = model.DKNgaySinh;
                taiKhoan.Email = model.DKEmail;
                taiKhoan.DiaChi = model.DKDiaChi;
                taiKhoan.DienThoai = model.DKDienThoai;

                response = client.PostAsJsonAsync("api/TaiKhoan", taiKhoan).Result;                
                if (response.IsSuccessStatusCode)
                {
                    Session["KetQuaDangKy"] = "Đăng ký thành công!";
                }
                else
                {
                    Session["KetQuaDangKy"] = "Đăng ký thất bại! Thông tin đăng ký không hợp lệ !";
                }
            }            
            return RedirectToAction("DangNhap", "Account");
        }

        public ActionResult CapNhatThongTinOpenID()
        {
            return View();
        }

        public ActionResult UpdateOpenID(HomeModel model)
        {
            try
            {
                if (string.IsNullOrEmpty(model.DKUserName))
                {
                    ViewBag.KetQuaDangNhap = "Fail";
                    return View("DangNhap");
                }
                else
                {
                    //Insert vao db
                    TaiKhoan taiKhoan = new TaiKhoan();
                    taiKhoan.UserName = model.DKUserName;
                    taiKhoan.OpenID = model.OpenID;
                    taiKhoan.HoTen = model.DKHoTen;

                    HttpClient client;
                    client = new HttpClient();
                    client.BaseAddress = new Uri("http://localhost:3333/");
                    client.DefaultRequestHeaders.Accept.Add(
                        new MediaTypeWithQualityHeaderValue("application/json"));
                    HttpResponseMessage response = client.PostAsJsonAsync("api/OpenID", taiKhoan).Result;
                    //Lấy thông tin tài khoản trả về.                    
                    HttpResponseMessage responseWS = client.GetAsync("api/OpenId/" + model.OpenID).Result;
                    if (responseWS.IsSuccessStatusCode)
                    {
                        TaiKhoan tk = (TaiKhoan)responseWS.Content.ReadAsAsync<TaiKhoan>().Result;
                        if (tk != null)
                        {
                            FormsAuthentication.SetAuthCookie(tk.UserName, false);
                            Session["TaiKhoan"] = tk;
                            return RedirectToAction("Index", "Home");
                        }
                    }
                    else
                    {
                        ViewBag.KetQuaDangNhap = "Fail";
                        return View("DangNhap");
                    }
                }
                ViewBag.KetQuaDangNhap = "Fail";
                return View("DangNhap");
                
            }
            catch (Exception ex)
            {
                ViewBag.KetQuaDangNhap = "Fail";
                return View("DangNhap");
            }
            
        }
        
        [ValidateInput(false)]
        public ActionResult Authenticate(string returnUrl)
        {
            var response = openid.GetResponse();
            if (response == null)
            {
                //Let us submit the request to OpenID provider
                Identifier id;
                if (Identifier.TryParse(Request.Form["openid_identifier"], out id))
                {
                    try
                    {
                        var request = openid.CreateRequest(
                                             Request.Form["openid_identifier"]);
                        return request.RedirectingResponse.AsActionResult();
                    }
                    catch (ProtocolException ex)
                    {
                        Session["MessageType"] = "KetQuaDangNhap";
                        return RedirectToAction("DangNhap", "Account");
                    }
                }

                Session["MessageType"] = "KetQuaDangNhap";
                return RedirectToAction("DangNhap", "Account");
            }

            //Let us check the response
            switch (response.Status)
            {

                case AuthenticationStatus.Authenticated:
                    {
                        HomeModel hm = new HomeModel();
                        hm.OpenID = response.ClaimedIdentifier;
                        TaiKhoan tk = null;

                        //Kiểm tra tài khoản tương ứng với chuối OpenID
                        HttpClient client;
                        client = new HttpClient();
                        client.BaseAddress = new Uri("http://localhost:3333/");
                        client.DefaultRequestHeaders.Accept.Add(
                            new MediaTypeWithQualityHeaderValue("application/json"));

                        string hashOpenID = CalculateMD5Hash(hm.OpenID);
                        HttpResponseMessage responseWS = client.GetAsync("api/OpenId/" + hashOpenID).Result;

                        if (responseWS.IsSuccessStatusCode)
                        {
                            tk = (TaiKhoan)responseWS.Content.ReadAsAsync<TaiKhoan>().Result;
                            if (tk != null)
                            {
                                FormsAuthentication.SetAuthCookie(tk.UserName, false);
                                Session["TaiKhoan"] = tk;
                                return RedirectToAction("Index", "Home");
                            }
                            else
                            {
                                ViewBag.OpenID = hashOpenID;
                                return View("CapNhatThongTinOpenID");
                            }
                        }
                        else
                        {
                            Session["MessageType"] = "KetQuaDangNhap";
                            return RedirectToAction("DangNhap", "Account");
                        }
                        break;
                    }
                case AuthenticationStatus.Canceled:
                    {
                        Session["MessageType"] = "KetQuaDangNhap";
                        return RedirectToAction("DangNhap", "Account");
                    }
                case AuthenticationStatus.Failed:
                    {
                        Session["MessageType"] = "KetQuaDangNhap";
                        return RedirectToAction("DangNhap", "Account");
                    }                    
            }

            return new EmptyResult();
        }

        public string CalculateMD5Hash(string input)
        {
            // step 1, calculate MD5 hash from input
            MD5 md5 = System.Security.Cryptography.MD5.Create();
            byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
            byte[] hash = md5.ComputeHash(inputBytes);

            // step 2, convert byte array to hex string
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                sb.Append(hash[i].ToString("X2"));
            }
            return sb.ToString();
        }


        [HttpGet]
        public ActionResult FacebookLogin(string token)
        {
            WebClient client = new WebClient();
            string JsonResult = client.DownloadString(string.Concat(
                   "https://graph.facebook.com/me?access_token=", token));
            // Json.Net is really helpful if you have to deal
            // with Json from .Net http://json.codeplex.com/
            JObject jsonUserInfo = JObject.Parse(JsonResult);
            // you can get more user's info here. Please refer to:
            //     http://developers.facebook.com/docs/reference/api/user/
            TaiKhoan tk = new TaiKhoan();
            tk.HoTen = jsonUserInfo.Value<string>("name");
           // tk.UserName = jsonUserInfo.Value<string>("username");
            tk.Email = jsonUserInfo.Value<string>("email");
            tk.UserName = tk.Email;
            tk.DiaChi = jsonUserInfo.Value<string>("locale");
            string facebook_userID = jsonUserInfo.Value<string>("id");

            //Kiểm tra tồn tại của tài khoản.
            HttpClient HttpClient;
            HttpClient = new HttpClient();
            HttpClient.BaseAddress = new Uri("http://localhost:3333/");
            HttpClient.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage response = HttpClient.GetAsync("api/FacebookOAuth/"+tk.UserName+"/"+tk.Email).Result;

            TaiKhoan taiKhoan=null;
            if (response.IsSuccessStatusCode)
            {
                taiKhoan = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
            }

            if (taiKhoan == null)
            {
                //Them moi rui lay id
                response = HttpClient.PostAsJsonAsync("api/FacebookOAuth", tk).Result;
                response = HttpClient.GetAsync("api/FacebookOAuth/" + tk.UserName + "/" + tk.Email).Result;
                if (response.IsSuccessStatusCode)
                {
                    taiKhoan = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
                }
                if (taiKhoan != null)
                {
                    FormsAuthentication.SetAuthCookie(tk.UserName, false);
                    Session["TaiKhoan"] = tk;
                    return RedirectToAction("Index", "Home");
                }
            }
            else
            {
                //Nếu thêm mới thì phải lấy về ID của tài khoản
                FormsAuthentication.SetAuthCookie(tk.UserName, false);
                Session["TaiKhoan"] = tk;
                return RedirectToAction("Index", "Home");
            }
            Session["MessageType"] = "KetQuaDangNhap";
            return RedirectToAction("DangNhap", "Account");
        }


        public ActionResult DangXuat()
        {
            if (Session["TaiKhoan"] != null)
            {
                Session["TaiKhoan"] = null;
            }
            return RedirectToAction("DangNhap", "Account");
        }


        public ActionResult KiemTraTaiKhoan(String TenDangNhap)
        {
            //Truy cập restful webservice để kiểm tra tài khoản.
            HttpClient client;
            client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:3333/");
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage response = client.GetAsync("api/TaiKhoan/" + TenDangNhap).Result;

            bool UserNameHopLe = false;
            if (response.IsSuccessStatusCode)
            {
                TaiKhoan taiKhoan = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
                if (taiKhoan != null)
                {
                    UserNameHopLe = false;
                }
                else
                {
                    UserNameHopLe = true;
                }
            }
            var data = new
            {
                IsValidUserName = UserNameHopLe,
            };
            return Json(data);
        }
        
        public ActionResult DangNhap()
        {
            if ( "KetQuaDangNhap" == Session["MessageType"])
            {
                Session["MessageType"] = null;
                ViewBag.KetQuaDangNhap = "Fail";
            }
            else if ("KetQuaDangKy" == Session["MessageType"])
            {
                ViewBag.KetQuaDangKy = Session["KetQuaDangKy"];
                Session["MessageType"] = null;
                Session["KetQuaDangKy"] = null;
            }
            return View();
        }

        [HttpPost]
        public ActionResult DangNhap(HomeModel model)
        {
            HttpClient client;
            client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:3333/");
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            HttpResponseMessage response = client.GetAsync("api/TaiKhoan/" + model.DNUsername + "/" + model.DNMatKhau).Result;

            if (response.IsSuccessStatusCode)
            {
                TaiKhoan taiKhoan = (TaiKhoan)response.Content.ReadAsAsync<TaiKhoan>().Result;
                if (taiKhoan != null)
                {
                    FormsAuthentication.SetAuthCookie(taiKhoan.UserName, false);
                    Session["TaiKhoan"] = taiKhoan;
                    return RedirectToAction("Index", "Home");
                }
            }
            Session["MessageType"] = "KetQuaDangNhap";
            return RedirectToAction("DangNhap", "Account"); 
        }

        public WrapJsonResult CapNhatTaiKhoan(HttpPostedFileWrapper HinhAnh, string HoTen, string NgaySinh, string Password, string NhapLaiPassword, string DiaChi, string DienThoai, string Email, string Id)
        {
            try
            {
                bool thongTinHopLe = true;
                if (string.IsNullOrEmpty(HoTen) || string.IsNullOrEmpty(Password) || string.IsNullOrEmpty(NhapLaiPassword))
                {
                    thongTinHopLe = false;
                }

                if (Password.CompareTo(NhapLaiPassword) != 0)
                {
                    thongTinHopLe = false;
                }

                if (thongTinHopLe)
                {
                    TaiKhoan taiKhoan = new TaiKhoan();
                    taiKhoan.Email = Email;
                    taiKhoan.Password = Password;
                    taiKhoan.HoTen = HoTen;
                    taiKhoan.NgaySinh = Convert.ToDateTime(NgaySinh);
                    taiKhoan.Id = Convert.ToInt32(Id);
                    taiKhoan.Password = Password;
                    taiKhoan.DienThoai = DienThoai;
                    taiKhoan.DiaChi = DiaChi;

                    if (HinhAnh != null && HinhAnh.ContentLength > 0)
                    {
                        byte[] image = new byte[HinhAnh.ContentLength];
                        HinhAnh.InputStream.Read(image, 0, HinhAnh.ContentLength);
                        taiKhoan.HinhAnh = image;
                    }

                    //Goi restful webservice.
                    HttpClient client;
                    client = new HttpClient();
                    client.BaseAddress = new Uri("http://localhost:3333/");
                    client.DefaultRequestHeaders.Accept.Add(
                        new MediaTypeWithQualityHeaderValue("application/json"));
                    HttpResponseMessage response = client.PutAsJsonAsync<TaiKhoan>("api/TaiKhoan", taiKhoan).Result;

                    if (response.IsSuccessStatusCode)
                    {

                        return new WrapJsonResult
                        {
                            Data = new
                            {
                                IsValid = true,
                            }
                        };
                    }
                    return new WrapJsonResult
                    {
                        Data = new
                        {
                            IsValid = false,
                        }
                    };
                }
                else
                {
                    return new WrapJsonResult
                    {
                        Data = new
                        {
                            IsValid = false,
                        }
                    };
                }
            }
            catch (Exception ex)
            {
                return new WrapJsonResult
                {
                    Data = new
                    {
                        IsValid = false,
                    }
                };
            }

        }

        #region Status Codes
        private static string ErrorCodeToString(MembershipCreateStatus createStatus)
        {
            // See http://go.microsoft.com/fwlink/?LinkID=177550 for
            // a full list of status codes.
            switch (createStatus)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    return "User name already exists. Please enter a different user name.";

                case MembershipCreateStatus.DuplicateEmail:
                    return "A user name for that e-mail address already exists. Please enter a different e-mail address.";

                case MembershipCreateStatus.InvalidPassword:
                    return "The password provided is invalid. Please enter a valid password value.";

                case MembershipCreateStatus.InvalidEmail:
                    return "The e-mail address provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidAnswer:
                    return "The password retrieval answer provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidQuestion:
                    return "The password retrieval question provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidUserName:
                    return "The user name provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.ProviderError:
                    return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                case MembershipCreateStatus.UserRejected:
                    return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                default:
                    return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
            }
        }
        #endregion
    }
}
